﻿using System;
using Domain;

namespace Presentation
{
    public class PresenterMessage
    {
        public const string KeyIsNotSet = "Enter key";
        public const string ValueIsNotSet = "Enter value";
        public const string InvalidFormat = "Invalid integer format";
        public const string TooLongNumber = "Too long number";
        public const string EmptyHeap = "Heap is empty";

        public const string InsertSuccessful = "Item is inserted successfully";
        public const string MinimumDeleted = "Item with minimal key is deleted";
    }

    public class Presenter
    {
        private IView view;
        private ILogger log;
        private readonly LeftSideHeap heap = new LeftSideHeap();

        public Presenter(IView view, ILogger log)
        {
            if (view == null || log == null)
            {
                throw new ArgumentNullException();
            }

            this.log = log;

            this.view = view;
            this.view.Key = "";
            this.view.Value = "";
            this.view.MinValue = "";
            this.view.Status = "";
            setActions();
        }

        private void setActions()
        {
            view.OnInsert += onInsert;
            view.OnGetMin += onGetMin;
            view.OnDeleteMin += onDeleteMin;
            view.OnDataChanged += onDataChanged;
        }

        public void setView(IView newView)
        {
            view = newView;
            setActions();
        }

        public void setLogger(ILogger logger)
        {
            view.Log = "";
            log = logger;
        }

        private void insertKeyValueInHeap(string keyStr, string valueStr)
        {
            var key = Convert.ToInt32(keyStr);
            var value = new IntHeapItemValue(Convert.ToInt32(valueStr));
            heap.insert(new HeapItem(key, value));
        }

        private void tryInsert(string key, string value)
        {
            insertKeyValueInHeap(key, value);
            view.Status = PresenterMessage.InsertSuccessful;
            log.Write("New element with key=" + key + ", value=" + value + " was added to heap");
        }

        private void onInsert()
        {
            if (view.Key.Equals(""))
            {
                view.Status = PresenterMessage.KeyIsNotSet;
                return;
            }
            if (view.Value.Equals(""))
            {
                view.Status = PresenterMessage.ValueIsNotSet;
                return;
            }

            try
            {
                tryInsert(view.Key, view.Value);
            }
            catch (FormatException)
            {
                view.Status = PresenterMessage.InvalidFormat;
            }
            catch (OverflowException)
            {
                view.Status = PresenterMessage.TooLongNumber;
            }
            view.Log = log.Read();
        }

        private void onGetMin()
        {
            var min = heap.getMin();
            if (min == null)
            {
                view.MinValue = "";
                view.Status = PresenterMessage.EmptyHeap;
                log.Write(PresenterMessage.EmptyHeap);
            }
            else
            {
                view.MinValue = min.ToString();
                view.Status = "";
                log.Write("Element with minimal key: " + view.MinValue);
            }
            view.Log = log.Read();
        }

        private void onDeleteMin()
        {
            var min = heap.deleteMin();
            if (min == null)
            {
                view.MinValue = "";
                view.Status = PresenterMessage.EmptyHeap;
                log.Write(PresenterMessage.EmptyHeap);
            }
            else
            {
                view.MinValue = min.ToString();
                view.Status = PresenterMessage.MinimumDeleted;
                log.Write("Element with minimal key (value=" + view.MinValue + ") is deleted");
            }
            view.Log = log.Read();
        }

        private void onDataChanged()
        {
            view.Status = "";
        }
    }
}
